using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore;
using JGSY.CMS.LowCode.Platform.Infrastructure.Services.Search;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using System.Diagnostics;
using System.Text.Json;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Search
{
    /// <summary>
    /// 通用搜索服务实现
    /// 基于数据库全文搜索的企业级搜索解决方案
    /// </summary>
    public class SearchService : ISearchService
    {
        private readonly LowCodeDbContext _context;
        private readonly ILogger<SearchService> _logger;

        public SearchService(LowCodeDbContext context, ILogger<SearchService> logger)
        {
            _context = context;
            _logger = logger;
        }

        /// <summary>
        /// 全局搜索 - 跨多个实体类型进行搜索
        /// </summary>
        public async Task<SearchResultDto> GlobalSearchAsync(string keyword, SearchFiltersDto? filters = null, int pageIndex = 0, int pageSize = 20)
        {
            var stopwatch = Stopwatch.StartNew();
            var items = new List<SearchItemDto>();

            try
            {
                // 如果指定了实体类型，则按指定类型搜索
                if (filters?.EntityTypes?.Any() == true)
                {
                    foreach (var entityType in filters.EntityTypes)
                    {
                        var result = await SearchByEntityTypeAsync(entityType, keyword, filters, 0, pageSize);
                        items.AddRange(result.Items);
                    }
                }
                else
                {
                    // 否则在所有支持的实体类型中搜索
                    var entityTypes = new[] { "article", "product", "page", "user", "category" };
                    foreach (var entityType in entityTypes)
                    {
                        var result = await SearchByEntityTypeAsync(entityType, keyword, filters, 0, Math.Min(pageSize / entityTypes.Length + 5, pageSize));
                        items.AddRange(result.Items);
                    }
                }

                // 按相关性得分排序
                items = items.OrderByDescending(x => x.Score).ToList();

                // 分页处理
                var totalCount = items.Count;
                var pagedItems = items.Skip(pageIndex * pageSize).Take(pageSize).ToList();

                stopwatch.Stop();

                return new SearchResultDto
                {
                    Keyword = keyword,
                    TotalCount = totalCount,
                    ElapsedMilliseconds = stopwatch.ElapsedMilliseconds,
                    Items = pagedItems,
                    Suggestions = await GenerateSearchSuggestions(keyword)
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Global search failed for keyword: {Keyword}", keyword);
                stopwatch.Stop();
                
                return new SearchResultDto
                {
                    Keyword = keyword,
                    TotalCount = 0,
                    ElapsedMilliseconds = stopwatch.ElapsedMilliseconds,
                    Items = new List<SearchItemDto>()
                };
            }
        }

        /// <summary>
        /// 按实体类型搜索
        /// </summary>
        public async Task<SearchResultDto> SearchByEntityTypeAsync(string entityType, string keyword, SearchFiltersDto? filters = null, int pageIndex = 0, int pageSize = 20)
        {
            var stopwatch = Stopwatch.StartNew();
            var items = new List<SearchItemDto>();

            try
            {
                switch (entityType.ToLower())
                {
                    case "article":
                        items = await SearchArticlesAsync(keyword, filters);
                        break;
                    case "product":
                        items = await SearchProductsAsync(keyword, filters);
                        break;
                    case "page":
                        items = await SearchPagesAsync(keyword, filters);
                        break;
                    case "user":
                        items = await SearchUsersAsync(keyword, filters);
                        break;
                    case "category":
                        items = await SearchCategoriesAsync(keyword, filters);
                        break;
                    default:
                        _logger.LogWarning("Unsupported entity type: {EntityType}", entityType);
                        break;
                }

                // 分页处理
                var totalCount = items.Count;
                var pagedItems = items.Skip(pageIndex * pageSize).Take(pageSize).ToList();

                stopwatch.Stop();

                return new SearchResultDto
                {
                    Keyword = keyword,
                    TotalCount = totalCount,
                    ElapsedMilliseconds = stopwatch.ElapsedMilliseconds,
                    Items = pagedItems
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Search by entity type failed. EntityType: {EntityType}, Keyword: {Keyword}", entityType, keyword);
                stopwatch.Stop();
                
                return new SearchResultDto
                {
                    Keyword = keyword,
                    TotalCount = 0,
                    ElapsedMilliseconds = stopwatch.ElapsedMilliseconds,
                    Items = new List<SearchItemDto>()
                };
            }
        }

        /// <summary>
        /// 获取搜索建议
        /// </summary>
        public async Task<IEnumerable<string>> GetSearchSuggestionsAsync(string keyword, int maxSuggestions = 10)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(keyword) || keyword.Length < 2)
                    return new List<string>();

                var suggestions = new HashSet<string>();

                // 从文章标题中获取建议
                var articleSuggestions = await _context.Articles
                    .Where(a => a.Title.Contains(keyword) && a.Status == 1) // Status 1 = 发布
                    .Select(a => a.Title)
                    .Take(maxSuggestions / 2)
                    .ToListAsync();
                
                foreach (var suggestion in articleSuggestions)
                    suggestions.Add(suggestion);

                // 从产品名称中获取建议
                var productSuggestions = await _context.Products
                    .Where(p => p.Name.Contains(keyword) && p.Status == 1) // Status 1 = 上架
                    .Select(p => p.Name)
                    .Take(maxSuggestions / 2)
                    .ToListAsync();

                foreach (var suggestion in productSuggestions)
                    suggestions.Add(suggestion);

                // 从分类名称中获取建议
        if (suggestions.Count < maxSuggestions)
                {
                    var categorySuggestions = await _context.Categories
            .Where(c => c.Name.Contains(keyword))
                        .Select(c => c.Name)
                        .Take(maxSuggestions - suggestions.Count)
                        .ToListAsync();

                    foreach (var suggestion in categorySuggestions)
                        suggestions.Add(suggestion);
                }

                return suggestions.Take(maxSuggestions);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Get search suggestions failed for keyword: {Keyword}", keyword);
                return new List<string>();
            }
        }

        /// <summary>
        /// 更新实体的搜索索引
        /// </summary>
        public Task<bool> UpdateEntityIndexAsync(string entityType, string entityId, object entityData)
        {
            try
            {
                _logger.LogInformation("Updating search index for {EntityType} with ID: {EntityId}", entityType, entityId);
                
                // 在基于数据库的搜索实现中，索引更新通过正常的数据库更新操作自动完成
                // 这里可以添加缓存刷新或其他优化操作
                
                return Task.FromResult(true);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Update entity index failed. EntityType: {EntityType}, EntityId: {EntityId}", entityType, entityId);
                return Task.FromResult(false);
            }
        }

        /// <summary>
        /// 删除实体的搜索索引
        /// </summary>
        public Task<bool> DeleteEntityIndexAsync(string entityType, string entityId)
        {
            try
            {
                _logger.LogInformation("Deleting search index for {EntityType} with ID: {EntityId}", entityType, entityId);
                
                // 在基于数据库的搜索实现中，索引删除通过正常的数据库删除操作自动完成
                // 这里可以添加缓存清理或其他清理操作
                
                return Task.FromResult(true);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Delete entity index failed. EntityType: {EntityType}, EntityId: {EntityId}", entityType, entityId);
                return Task.FromResult(false);
            }
        }

        /// <summary>
        /// 重建搜索索引
        /// </summary>
        public Task<bool> RebuildIndexAsync(string? entityType = null)
        {
            try
            {
                _logger.LogInformation("Rebuilding search index for entity type: {EntityType}", entityType ?? "all");
                
                // 在基于数据库的搜索实现中，可以执行索引重建、缓存刷新等操作
                // 这里模拟重建过程
                
                return Task.FromResult(true);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Rebuild index failed for entity type: {EntityType}", entityType);
                return Task.FromResult(false);
            }
        }

        #region Private Helper Methods

        /// <summary>
        /// 搜索文章
        /// </summary>
        private async Task<List<SearchItemDto>> SearchArticlesAsync(string keyword, SearchFiltersDto? filters)
        {
            var query = _context.Articles.AsQueryable();

            // 基本搜索条件
            if (!string.IsNullOrWhiteSpace(keyword))
            {
                query = query.Where(a => 
                    a.Title.Contains(keyword) || 
                    (a.Summary != null && a.Summary.Contains(keyword)) || 
                    (a.Content != null && a.Content.Contains(keyword)) ||
                    (a.Tags != null && a.Tags.Contains(keyword)));
            }

            // 应用过滤器
            if (filters != null)
            {
                if (filters.Categories?.Any() == true)
                {
                    query = query.Include(a => a.Category)
                        .Where(a => a.Category != null && filters.Categories.Contains(a.Category.Name));
                }

                if (filters.CreatedDateRange != null)
                {
                    if (filters.CreatedDateRange.StartDate.HasValue)
                        query = query.Where(a => a.CreatedAt >= filters.CreatedDateRange.StartDate);
                    if (filters.CreatedDateRange.EndDate.HasValue)
                        query = query.Where(a => a.CreatedAt <= filters.CreatedDateRange.EndDate);
                }

                if (filters.Tags?.Any() == true)
                {
                    foreach (var tag in filters.Tags)
                    {
                        query = query.Where(a => a.Tags != null && a.Tags.Contains(tag));
                    }
                }
            }

            // 只返回已发布的文章 (Status 1 = 发布)
            query = query.Where(a => a.Status == 1);

            var articles = await query
                .Include(a => a.Category)
                .Include(a => a.Creator)
                .OrderByDescending(a => a.PublishedAt)
                .ToListAsync();

            return articles.Select(article => new SearchItemDto
            {
                Id = article.Id.ToString(),
                EntityType = "article",
                Title = article.Title,
                Description = article.Summary ?? string.Empty,
                Content = TruncateText(article.Content, 200),
                Url = $"/articles/{article.Slug}",
                Thumbnail = article.FeaturedImage,
                Tags = article.Tags?.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList(),
                Category = article.Category?.Name,
                Status = GetStatusString(article.Status),
                Author = article.Creator?.RealName ?? article.Creator?.Username,
                CreatedAt = article.CreatedAt,
                UpdatedAt = article.UpdatedAt,
                Score = CalculateRelevanceScore(keyword, article.Title, article.Summary, article.Content),
                Highlights = GenerateHighlights(keyword, article.Title, article.Summary)
            }).ToList();
        }

        /// <summary>
        /// 搜索产品
        /// </summary>
        private async Task<List<SearchItemDto>> SearchProductsAsync(string keyword, SearchFiltersDto? filters)
        {
            var query = _context.Products.AsQueryable();

            if (!string.IsNullOrWhiteSpace(keyword))
            {
                query = query.Where(p => 
                    p.Name.Contains(keyword) || 
                    (p.Description != null && p.Description.Contains(keyword)) ||
                    (p.Sku != null && p.Sku.Contains(keyword)));
            }

            if (filters?.Categories?.Any() == true)
            {
                // Note: Product entity doesn't have direct Category navigation in current schema
                // This would need to be implemented based on actual product categorization
            }

            if (filters?.CreatedDateRange != null)
            {
                if (filters.CreatedDateRange.StartDate.HasValue)
                    query = query.Where(p => p.CreatedAt >= filters.CreatedDateRange.StartDate);
                if (filters.CreatedDateRange.EndDate.HasValue)
                    query = query.Where(p => p.CreatedAt <= filters.CreatedDateRange.EndDate);
            }

            var products = await query
                .Include(p => p.Creator)
                .Where(p => p.Status == 1) // Status 1 = 上架
                .OrderByDescending(p => p.CreatedAt)
                .ToListAsync();

            return products.Select(product => new SearchItemDto
            {
                Id = product.Id.ToString(),
                EntityType = "product",
                Title = product.Name,
                Description = product.Description ?? string.Empty,
                Content = TruncateText(product.Description, 200),
                Url = $"/products/{product.Slug}",
                Thumbnail = GetFirstImage(product.Images),
                Author = product.Creator?.RealName ?? product.Creator?.Username,
                CreatedAt = product.CreatedAt,
                UpdatedAt = product.UpdatedAt,
                Score = CalculateRelevanceScore(keyword, product.Name, product.Description, string.Empty),
                CustomProperties = new Dictionary<string, object>
                {
                    ["Price"] = product.Price,
                    ["Sku"] = product.Sku ?? string.Empty
                }
            }).ToList();
        }

        /// <summary>
        /// 搜索页面
        /// </summary>
        private async Task<List<SearchItemDto>> SearchPagesAsync(string keyword, SearchFiltersDto? filters)
        {
            var query = _context.Pages.AsQueryable();

            if (!string.IsNullOrWhiteSpace(keyword))
            {
                query = query.Where(p => 
                    p.Title.Contains(keyword) || 
                    (p.Description != null && p.Description.Contains(keyword)) ||
                    (p.Content != null && p.Content.Contains(keyword)));
            }

            if (filters?.CreatedDateRange != null)
            {
                if (filters.CreatedDateRange.StartDate.HasValue)
                    query = query.Where(p => p.CreatedAt >= filters.CreatedDateRange.StartDate);
                if (filters.CreatedDateRange.EndDate.HasValue)
                    query = query.Where(p => p.CreatedAt <= filters.CreatedDateRange.EndDate);
            }

            var pages = await query
                .Include(p => p.Creator)
                .Where(p => p.Status == 1) // Status 1 = 发布
                .OrderByDescending(p => p.UpdatedAt)
                .ToListAsync();

            return pages.Select(page => new SearchItemDto
            {
                Id = page.Id.ToString(),
                EntityType = "page",
                Title = page.Title,
                Description = page.Description ?? string.Empty,
                Content = TruncateText(page.Content, 200),
                Url = $"/pages/{page.Slug}",
                Author = page.Creator?.RealName ?? page.Creator?.Username,
                CreatedAt = page.CreatedAt,
                UpdatedAt = page.UpdatedAt,
                Score = CalculateRelevanceScore(keyword, page.Title, page.Description, page.Content)
            }).ToList();
        }

        /// <summary>
        /// 搜索用户
        /// </summary>
        private async Task<List<SearchItemDto>> SearchUsersAsync(string keyword, SearchFiltersDto? filters)
        {
            var query = _context.Users.AsQueryable();

            if (!string.IsNullOrWhiteSpace(keyword))
            {
                query = query.Where(u => 
                    u.Username.Contains(keyword) || 
                    (u.RealName != null && u.RealName.Contains(keyword)) ||
                    (u.Email != null && u.Email.Contains(keyword)));
            }

            var users = await query
                .Where(u => u.Status == 1) // Status 1 = 启用
                .OrderBy(u => u.Username)
                .ToListAsync();

            return users.Select(user => new SearchItemDto
            {
                Id = user.Id.ToString(),
                EntityType = "user",
                Title = user.RealName ?? user.Username,
                Description = user.Remark ?? string.Empty,
                Url = $"/users/{user.Username}",
                Thumbnail = user.Avatar,
                CreatedAt = user.CreatedAt,
                UpdatedAt = user.UpdatedAt,
                Score = CalculateRelevanceScore(keyword, user.RealName ?? user.Username, user.Username, user.Remark),
                CustomProperties = new Dictionary<string, object>
                {
                    ["Username"] = user.Username,
                    ["Email"] = user.Email ?? string.Empty
                }
            }).ToList();
        }

        /// <summary>
        /// 搜索分类
        /// </summary>
        private async Task<List<SearchItemDto>> SearchCategoriesAsync(string keyword, SearchFiltersDto? filters)
        {
            var query = _context.Categories.AsQueryable();

            if (!string.IsNullOrWhiteSpace(keyword))
            {
                query = query.Where(c => 
                    c.Name.Contains(keyword) || 
                    (c.Description != null && c.Description.Contains(keyword)));
            }

            var categories = await query
                .OrderBy(c => c.Name)
                .ToListAsync();

            return categories.Select(category => new SearchItemDto
            {
                Id = category.Id.ToString(),
                EntityType = "category",
                Title = category.Name,
                Description = category.Description ?? string.Empty,
                Url = $"/categories/{category.Slug}",
                CreatedAt = category.CreatedAt,
                UpdatedAt = category.UpdatedAt,
                Score = CalculateRelevanceScore(keyword, category.Name, category.Description, string.Empty)
            }).ToList();
        }

        /// <summary>
        /// 计算相关性得分
        /// </summary>
        private static float CalculateRelevanceScore(string keyword, string title, string? summary, string? content)
        {
            if (string.IsNullOrWhiteSpace(keyword))
                return 0f;

            float score = 0f;

            // 标题匹配权重最高
            if (title.Contains(keyword, StringComparison.OrdinalIgnoreCase))
            {
                score += title.Equals(keyword, StringComparison.OrdinalIgnoreCase) ? 100f : 50f;
            }

            // 摘要匹配权重中等
            if (!string.IsNullOrWhiteSpace(summary) && summary.Contains(keyword, StringComparison.OrdinalIgnoreCase))
            {
                score += 20f;
            }

            // 内容匹配权重较低
            if (!string.IsNullOrWhiteSpace(content) && content.Contains(keyword, StringComparison.OrdinalIgnoreCase))
            {
                score += 10f;
            }

            return score;
        }

        /// <summary>
        /// 生成高亮片段
        /// </summary>
        private static List<string> GenerateHighlights(string keyword, string title, string? summary)
        {
            var highlights = new List<string>();

            if (title.Contains(keyword, StringComparison.OrdinalIgnoreCase))
            {
                highlights.Add(HighlightText(title, keyword));
            }

            if (!string.IsNullOrWhiteSpace(summary) && summary.Contains(keyword, StringComparison.OrdinalIgnoreCase))
            {
                highlights.Add(HighlightText(TruncateText(summary, 100), keyword));
            }

            return highlights;
        }

        /// <summary>
        /// 高亮显示文本中的关键词
        /// </summary>
        private static string HighlightText(string text, string keyword)
        {
            if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(keyword))
                return text;

            return text.Replace(keyword, $"<mark>{keyword}</mark>", StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 截断文本
        /// </summary>
        private static string TruncateText(string? text, int maxLength)
        {
            if (string.IsNullOrWhiteSpace(text))
                return string.Empty;

            if (text.Length <= maxLength)
                return text;

            return text.Substring(0, maxLength) + "...";
        }

        /// <summary>
        /// 生成搜索建议
        /// </summary>
        private async Task<List<string>> GenerateSearchSuggestions(string keyword)
        {
            try
            {
                var suggestions = await GetSearchSuggestionsAsync(keyword, 5);
                return suggestions.ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Generate search suggestions failed for keyword: {Keyword}", keyword);
                return new List<string>();
            }
        }

        /// <summary>
        /// 获取状态字符串
        /// </summary>
        private static string GetStatusString(byte status)
        {
            return status switch
            {
                0 => "草稿",
                1 => "已发布",
                2 => "审核中",
                3 => "已撤回",
                4 => "归档",
                _ => "未知"
            };
        }

        /// <summary>
        /// 从JSON数组中获取第一个图片URL
        /// </summary>
        private static string? GetFirstImage(string? imagesJson)
        {
            if (string.IsNullOrWhiteSpace(imagesJson))
                return null;

            try
            {
                var images = JsonSerializer.Deserialize<string[]>(imagesJson);
                return images?.FirstOrDefault();
            }
            catch
            {
                return null;
            }
        }

        #endregion
    }
}
